package com.haoze.nurseapp.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.haoze.common.enumeration.StateEnum;
import com.haoze.common.model.OrdersFileIndexDataEntity;
import com.haoze.common.model.TaskExecuteBatchEntity;
import com.haoze.common.response.Result;
import com.haoze.common.response.ResultGenerator;
import com.haoze.common.utils.UUIDUtil;
import com.haoze.nurseapp.dao.*;
import com.haoze.nurseapp.model.*;
import com.haoze.nurseapp.service.InpDispensaryService;
import com.haoze.nurseapp.service.NursePatientOrderService;
import com.haoze.nurseapp.vo.BatchMedicalVO;
import com.haoze.nurseapp.vo.StaticDistributionVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @Author: Chenchao
 * @CreateTime: 2020-04-14 10:37
 */
@Service
public class InpDispensaryServiceImpl implements InpDispensaryService {

    @Resource
    private InpDispensaryMapper inpDispensaryMapper;

    @Resource
    UserMapper userMapper;

    @Resource
    StaticCenterMapper staticCenterMapper;

    @Resource
    TaskExecuteDetailMapper taskExecuteDetailMapper;

    @Resource
    NursePatientOrderService patientOrderService;

    @Resource
    TaskExecuteMapper taskExecuteMapper;

    @Resource
    OrdersFileIndexDataMapper ordersFileIndexDataMapper;

    @Override
    public Result queryList(String wardId, String dateTime, String startDate, String endDate) {
        String beginTime;
        String endTime;
        if(StringUtils.isNotEmpty(dateTime)) {
            beginTime = dateTime + " 00:00:00";
            endTime = dateTime + " 23:59:59";
        }else{
            beginTime = startDate + " 00:00:00";
            endTime = endDate + " 23:59:59";
        }
        List<Map<String,Object>> list = inpDispensaryMapper.queryList(wardId, beginTime, endTime);
        return ResultGenerator.genOkResult(list);
    }

    @Override
    public Result queryAppList(String wardId, String dateTime, String startDate, String endDate) {
        String beginTime;
        String endTime;
        if(StringUtils.isNotEmpty(dateTime)) {
            beginTime = dateTime + " 00:00:00";
            endTime = dateTime + " 23:59:59";
        }else{
            beginTime = startDate + " 00:00:00";
            endTime = endDate + " 23:59:59";
        }
        List<Map<String,Object>> list = inpDispensaryMapper.queryAppList(wardId, beginTime, endTime);
        return ResultGenerator.genOkResult(list);
    }

    @Override
    public Result docDetailList(String docNo, String type, Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        List<BatchMedicalVO> list = new ArrayList<>();
        switch (type) {
            case "ACCEPTED":
                list = inpDispensaryMapper.docAcceptedDetailList(docNo);
                break;
            case "UNACCEPTED":
                list = inpDispensaryMapper.docUnAcceptedDetailList(docNo);
                break;
            case "ALL":
                list = inpDispensaryMapper.docDetailList(docNo);
                break;
            case "DEFECT":
                list = inpDispensaryMapper.docDefectDetailList(docNo);
        }
        PageInfo<BatchMedicalVO> pageInfo = new PageInfo<>(list);
        return ResultGenerator.genOkResult(pageInfo);
    }

    @Override
    public Result lackMedical(List<DrugCollectionEntity> list) {
        String id = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()
                .getHeader("zuul_id");
        UserEntity currentUser = userMapper.selectByPrimaryKey(id);
        AtomicBoolean isCheck = new AtomicBoolean(false);
        StringBuilder sb = new StringBuilder();
        List<DrugCollectionEntity> resList = new CopyOnWriteArrayList<>();
        list.parallelStream().forEach(dc -> {
            if(inpDispensaryMapper.checkOrderIsStopByLack(dc.getDocNo(),dc.getPhamStdCode())>0){
                isCheck.set(true);
                sb.append("单据号：").append(dc.getDocNo()).append(",药品名称：").append(dc.getPhamName()).append("的医嘱已停止，无法收药");
            }
            dc.setCollectionId(UUIDUtil.randomString());
            dc.setReceivableCount(null == dc.getReceivableCount()?0:dc.getReceivableCount());
            dc.setDefectCount(null == dc.getDefectCount()?0:dc.getDefectCount());
            dc.setNurseId(currentUser.getUserId());
            dc.setNurseName(currentUser.getUserName());
            dc.setAcceptedCount(dc.getReceivableCount()-dc.getDefectCount());
            dc.setHospitalId(StateEnum.HOSPITAL_ID.getValue());
            dc.setDataVersion(1);
            //根据单据号和药品编码查看当前新增数量是否小于未领数量，退药数量小于未领数量，才能继续操作，如果超出则直接过滤
            if(inpDispensaryMapper.checkUnAccepted(dc.getPhamStdCode(),dc.getDocNo(),dc.getAcceptedCount(),dc.getDefectCount())>0){
                resList.add(dc);
            }
        });

        if(isCheck.get()){
            return ResultGenerator.genFailedResult(sb.toString());
        }

        inpDispensaryMapper.insertDrugCollectionEntity(resList);

        return ResultGenerator.genOkResult("核对完成");
    }

    @Override
    public Result bedList(String docNo, String phamStdCode, Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        PageInfo<BatchMedicalVO> pageInfo = new PageInfo<>(inpDispensaryMapper.bedList(docNo, phamStdCode));
        return ResultGenerator.genOkResult(pageInfo);
    }

    @Override
    public Result bedDetailList(String docNo, Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        PageInfo<BatchMedicalVO> pageInfo = new PageInfo<>(inpDispensaryMapper.bedDetailList(docNo));
//        pageInfo.setTotal(inpDispensaryMapper.bedDetailListTotal(docNo));
        return ResultGenerator.genOkResult(pageInfo);
    }

    @Override
    public Result docDefectDetailList(String docNo, Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        PageInfo<BatchMedicalVO> pageInfo = new PageInfo<>(inpDispensaryMapper.docDefectDetailList(docNo));
        return ResultGenerator.genOkResult(pageInfo);
    }

    @Override
    public Result queryReason() {
        return ResultGenerator.genOkResult(inpDispensaryMapper.queryReason());
    }

    @Override
    public Result docStaticDetailList(String startDate, String wardId, Integer page, Integer pageSize, String notInbarCodes, String barCode, String type, String searchValue) {
        //PageHelper.startPage(page, pageSize);
        //PageInfo<StaticDistributionVO> pageInfo = new PageInfo<>(inpDispensaryMapper.docStaticDetailList(startDate, getStartAndEndDate(startDate), wardId, StringUtils.isEmpty(notInbarCodes) ? null : notInbarCodes.split(","), barCode, type, searchValue));
        //Integer totalNum = inpDispensaryMapper.getTotalNum(startDate, getStartAndEndDate(startDate), wardId, StringUtils.isEmpty(notInbarCodes) ? null : notInbarCodes.split(","), barCode, type, searchValue);
        //pageInfo.setTotal(totalNum);
        //return ResultGenerator.genOkResult(pageInfo);
        List<StaticDistributionVO> staticDistributionVOS = inpDispensaryMapper.docStaticDetailList(startDate, getStartAndEndDate(startDate), wardId, StringUtils.isEmpty(notInbarCodes) ? null : notInbarCodes.split(","), barCode, type, searchValue);
        int totalLength = 0;
        if(CollectionUtils.isNotEmpty(staticDistributionVOS)){
            staticDistributionVOS = staticDistributionVOS.stream().sorted(Comparator.comparingInt(InpDispensaryServiceImpl::compareBedNo)
                    .thenComparing(StaticDistributionVO::getBatchTime))
                    .collect(Collectors.toList());
            totalLength = staticDistributionVOS.size();

            if (page != 0 && pageSize != 0) {
                staticDistributionVOS = staticDistributionVOS.stream().skip((page - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
            }
        }
        PageInfo<StaticDistributionVO> pageInfo = new PageInfo<StaticDistributionVO>(staticDistributionVOS);
        pageInfo.setTotal(totalLength);
        return ResultGenerator.genOkResult(pageInfo);
    }

    private static Integer compareBedNo(StaticDistributionVO map) {
        return Integer.parseInt(map.getBedNo());
    }

    @Override
    public Result queryReturnReason() {
        return ResultGenerator.genOkResult(inpDispensaryMapper.queryReturnReason());
    }

    @Override
    public Result docStaticDetailNum(String startDate, String wardId) {
        Map<String, BigDecimal> map = inpDispensaryMapper.docStaticDetailNum(startDate, getStartAndEndDate(startDate), wardId);
        map.put("TOTAL",map.get("UNRECEIVED").add(map.get("RECEIVE")));
        return ResultGenerator.genOkResult(map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result addReturn(List<StaticmedicineRecordEntity> list) {
        String id = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()
                .getHeader("zuul_id");
        UserEntity currentUser = userMapper.selectByPrimaryKey(id);
        List<TaskExecuteBatchEntity> taskExecuteDetailEntitys = new CopyOnWriteArrayList<>();
        AtomicBoolean isCheck = new AtomicBoolean(false);
        AtomicReference<String> code = new AtomicReference<>("");
        List<StaticmedicineRecordEntity> resList = new CopyOnWriteArrayList<>();
        list.forEach(dc -> {
            if(inpDispensaryMapper.checkOrderIsStop(dc.getBarCode()) > 0){
                code.set(dc.getBarCode());
                isCheck.set(true);
            }else {
                dc.setStaticmedicineId(UUIDUtil.randomString());
                dc.setExecutePersonId(currentUser.getUserId());
                dc.setExecutePerson(currentUser.getUserName());
                dc.setStatus("1");
                dc.setHospitalId(StateEnum.HOSPITAL_ID.getValue());
                dc.setDataVersion(1);
                if(inpDispensaryMapper.checkStaticUnAccept(dc.getBarCode())>0) {
                    String status;
                    String dataCode;
                    if (dc.getType().equals("receive")) {
                        StaticCenterEntity staticCenterEntity = staticCenterMapper.queryPersonIdByBarCode(dc.getBarCode(), null);
                        TaskExecuteBatchEntity taskExecuteBatchEntity = taskExecuteDetailMapper.queryInfoByBarCode(dc.getBarCode());
                        if("1".equalsIgnoreCase(staticCenterEntity.getBatch())){
                            status = "已加药";
                            dataCode = "61224789ffe9413fb84c981f14ec13ad";
                        }else{
                            status = "未加药";
                            dataCode = "e08165457f3442beaf5a5674daabf6f3";
                        }
                        OrdersFileIndexDataEntity fileIndexDataEntity = taskExecuteMapper.queryFileIndexData(taskExecuteBatchEntity.getTaskBatchId());
                        fileIndexDataEntity.setDataValue(status);
                        fileIndexDataEntity.setDataCode(dataCode);
                        ordersFileIndexDataMapper.updateByPrimaryKeySelective(fileIndexDataEntity);
                        taskExecuteDetailMapper.updateEmrFileIdById(taskExecuteBatchEntity.getTaskExecuteDetailId(),fileIndexDataEntity.getEmrFileId());
                        taskExecuteDetailEntitys.add(taskExecuteBatchEntity);
                    }
                    resList.add(dc);
                }
            }
        });
        if(isCheck.get()){
            return ResultGenerator.genFailedResult("条形码为"+code+"的医嘱已停止，请重新选择");
        }

        // 查询当前节点是否正处在待完成
        List<Map<String,Object>> listMap = new ArrayList<>();
        for (int j = 0; j < taskExecuteDetailEntitys.size(); j++) {
            Map<String,Object> entityMap = new HashMap<>();
            TaskExecuteBatchEntity taskExecuteDetailEntity = taskExecuteDetailEntitys.get(j);
            if(null == taskExecuteDetailEntity) continue;
            taskExecuteDetailEntity.setExecutePersonId(currentUser.getUserId());
            entityMap.put("taskExecuteDetailEntity",taskExecuteDetailEntity);
            entityMap.put("userId",currentUser.getUserId());
            listMap.add(entityMap);
        }
        try {
            int i = inpDispensaryMapper.insertStaticmedicineRecordEntity(resList);
            //创建下一个节点
            patientOrderService.createNextTaskNodeList(listMap,"");
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();
        }


        return ResultGenerator.genOkResult("核对完成");
    }

    @Override
    public Result pcDocDetailList(String docNo, String drugName, String reqId) {
        return ResultGenerator.genOkResult(inpDispensaryMapper.pcDocDetailList(docNo,drugName,reqId));
    }

    @Override
    public Result pcReceivedList(String docNo, String drugCode, String reqId) {
        return ResultGenerator.genOkResult(inpDispensaryMapper.pcReceivedList(docNo, drugCode, reqId));
    }

    @Override
    public Result pcDefectedList(String docNo, String drugCode, String reqId) {
        return ResultGenerator.genOkResult(inpDispensaryMapper.pcDefectedList(docNo, drugCode, reqId));
    }

    @Override
    public Result pcPatientPersonList(String docNo, String drugCode, String isPrint, String reqId,String prescNo) {
        return ResultGenerator.genOkResult(inpDispensaryMapper.pcPatientPersonList(docNo, drugCode, isPrint, reqId,prescNo));
    }

    @Override
    public Result pcPatientDrugList(String docNo, String patientInfo, String drugName, String reqId) {
        return ResultGenerator.genOkResult(inpDispensaryMapper.pcPatientDrugList(docNo,patientInfo,drugName,reqId));
    }

    @Override
    public Result pcPrintSendDrug(String docNo, String drugCode) {
        return ResultGenerator.genOkResult(inpDispensaryMapper.pcPrintSendDrug(docNo, drugCode));
    }

    @Override
    public Result pcWritePrintSendDrug(String docNo, String drugCode, String inpatNum) {
        if(inpDispensaryMapper.pcPrintSendDrug(docNo, drugCode)>0){
            return ResultGenerator.genOkResult(inpDispensaryMapper.pcUpdatePrintSendDrug(docNo, drugCode));
        }
        String id = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()
                .getHeader("zuul_id");
        PrintMarkEntity printMarkEntity = new PrintMarkEntity();
        printMarkEntity.setDrugCode(drugCode);
        printMarkEntity.setOrderNo(docNo);
        printMarkEntity.setPrintMarkId(UUIDUtil.randomString());
        printMarkEntity.setPrintUserId(id);
        printMarkEntity.setTimes(1);
        printMarkEntity.setType("5");
        printMarkEntity.setInpatNum(inpatNum);
        printMarkEntity.initAdd();
        return ResultGenerator.genOkResult(inpDispensaryMapper.pcWritePrintSendDrug(printMarkEntity));
    }

    @Override
    public Result pcNotSendInfo(String docNo,String patientInfo,String orders) {
        return ResultGenerator.genOkResult(inpDispensaryMapper.pcNotSendInfo(docNo,patientInfo,orders));
    }

    @Override
    public Result docAllStaticDetailList(String date, String wardId, Integer page, Integer pageSize, String notInbarCodes, String barCode, String type, String searchValue) {
        PageHelper.startPage(page, pageSize);
        PageInfo<StaticDistributionVO> pageInfo = new PageInfo<>(inpDispensaryMapper.docAllStaticDetailList(date, getStartAndEndDate(date), wardId, StringUtils.isEmpty(notInbarCodes) ? null : notInbarCodes.split(","), barCode, type, searchValue));
        return ResultGenerator.genOkResult(pageInfo);
    }

    @Override
    public Result pushFullStaticCenter(String date) {
        copyIntoStaticCenter(staticCenterMapper.pushFullStaticCenter(date));
        return ResultGenerator.genOkResult("同步完成");
    }

    private void copyIntoStaticCenter(List<Map<String, String>> list) {
        list.parallelStream().forEach(rs -> {
            String inpatNum = rs.get("PATIENT_NO") + "-1";
            String orderNo = rs.get("ORDER_NO");
            String batch = rs.get("BATCH");
            String doctorCode = rs.get("DOCTOR_CODE");
            String barcode = rs.get("BARCODE");
            String useDate = rs.get("USE_DATE");
            String useTime = rs.get("USE_TIME");
            String frequency = rs.get("FREQUENCY");
            String userId = staticCenterMapper.queryUserId(doctorCode);
            StaticCenterEntity staticCenterEntity = new StaticCenterEntity();
            staticCenterEntity.setBarCode(barcode);
            staticCenterEntity.setDataVersion(1);
            staticCenterEntity.setGmtCreate(new Date());
            staticCenterEntity.setGmtModify(new Date());
            staticCenterEntity.setHospitalId("80D024E29BF40C9DE0537A5B14AC1620");
            staticCenterEntity.setBatch(batch);
            staticCenterEntity.setInpatNum(inpatNum);
            staticCenterEntity.setOrderNo(orderNo);
            staticCenterEntity.setUseDate(useDate);
            staticCenterEntity.setUseTime(useTime);
            staticCenterEntity.setFreq(frequency);
            staticCenterEntity.setDoctorId(userId);
            staticCenterEntity.setStatus("0");
            staticCenterMapper.insert(staticCenterEntity);
        });
    }

    String getStartAndEndDate(String startDate){
        String endDate = startDate;
        try {
            Calendar cal = Calendar.getInstance();
            cal.setTime((new SimpleDateFormat("yyyy-MM-dd")).parse(startDate));
            cal.add(Calendar.DATE, 1);
            endDate = (new SimpleDateFormat("yyyy-MM-dd")).format(cal.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return endDate;
    }
}
